import * as fs from 'node:fs'
import * as path from 'node:path'
import logger from './logger'
import { getProjectRoot } from './util'

// 配置文件类型定义
export interface CabinetConfig {
  index: string
  name: string
  reverseOpenFlag: number
}

export interface SerialPortConfig {
  path: string
  baudRate: number
}

export interface LockConfig {
  gpioPort: number
  pollInterval: number
}

export interface RfidConfig {
  serialPort: SerialPortConfig
  antennaIds: number[]
  readingTimeout: number
  countdownInterval: number
}

export interface ScreenControlIds {
  cabinetIndex: string
  fileCount: string
  userName: string
  status: string
}

export interface ScreenConfig {
  serialPort: SerialPortConfig
  controlIds: ScreenControlIds
}

export interface HardwareConfig {
  lock: LockConfig
  rfid: RfidConfig
  screen: ScreenConfig
}

export interface MessageQueueConfig {
  maxLength: number
  cleanupThreshold: number
}

export interface SystemConfig {
  messageQueue: MessageQueueConfig
}

export interface AppConfig {
  cabinet: CabinetConfig
  hardware: HardwareConfig
  system: SystemConfig
}

// 默认配置
const defaultConfig: AppConfig = {
  cabinet: {
    index: '001',
    name: '用户名',
    reverseOpenFlag: 1,
  },
  hardware: {
    lock: {
      gpioPort: 20,
      pollInterval: 500,
    },
    rfid: {
      serialPort: {
        path: '/dev/ttyS1',
        baudRate: 115200,
      },
      antennaIds: [1, 2, 3, 4],
      readingTimeout: 5,
      countdownInterval: 1000,
    },
    screen: {
      serialPort: {
        path: '/dev/ttyS2',
        baudRate: 115200,
      },
      controlIds: {
        cabinetIndex: '0000',
        fileCount: '0010',
        userName: '0020',
        status: '0030',
      },
    },
  },
  system: {
    messageQueue: {
      maxLength: 10000,
      cleanupThreshold: 5000,
    },
  },
}

let cachedConfig: AppConfig | null = null

/**
 * 深度合并配置对象
 */
function deepMerge<T>(target: T, source: Partial<T>): T {
  const result = { ...target }

  for (const key in source) {
    if (source[key] !== undefined) {
      if (typeof source[key] === 'object' && source[key] !== null && !Array.isArray(source[key])) {
        result[key] = deepMerge(result[key], source[key] as any)
      }
      else {
        result[key] = source[key] as any
      }
    }
  }

  return result
}

/**
 * 验证配置项的完整性和有效性
 */
function validateConfig(config: Partial<AppConfig>): { isValid: boolean, errors: string[] } {
  const errors: string[] = []

  try {
    // 验证柜子配置
    if (config.cabinet) {
      if (!config.cabinet.index || typeof config.cabinet.index !== 'string') {
        errors.push('cabinet.index 必须是非空字符串')
      }
      if (!config.cabinet.name || typeof config.cabinet.name !== 'string') {
        errors.push('cabinet.name 必须是非空字符串')
      }
      if (config.cabinet.reverseOpenFlag !== undefined
        && typeof config.cabinet.reverseOpenFlag !== 'number') {
        errors.push('cabinet.reverseOpenFlag 必须是数字')
      }
    }

    // 验证硬件配置
    if (config.hardware) {
      // 验证锁配置
      if (config.hardware.lock) {
        if (typeof config.hardware.lock.gpioPort !== 'number'
          || config.hardware.lock.gpioPort < 0
          || config.hardware.lock.gpioPort > 40) {
          errors.push('hardware.lock.gpioPort 必须是0-40之间的有效GPIO引脚号')
        }
        if (typeof config.hardware.lock.pollInterval !== 'number'
          || config.hardware.lock.pollInterval < 100) {
          errors.push('hardware.lock.pollInterval 必须是大于等于100的数字(毫秒)')
        }
      }

      // 验证RFID配置
      if (config.hardware.rfid) {
        if (!config.hardware.rfid.serialPort?.path) {
          errors.push('hardware.rfid.serialPort.path 必须是有效的串口路径')
        }
        if (typeof config.hardware.rfid.serialPort?.baudRate !== 'number'
          || config.hardware.rfid.serialPort.baudRate <= 0) {
          errors.push('hardware.rfid.serialPort.baudRate 必须是大于0的数字')
        }
        if (!Array.isArray(config.hardware.rfid.antennaIds)
          || config.hardware.rfid.antennaIds.length === 0) {
          errors.push('hardware.rfid.antennaIds 必须是非空数组')
        }
        if (typeof config.hardware.rfid.readingTimeout !== 'number'
          || config.hardware.rfid.readingTimeout <= 0) {
          errors.push('hardware.rfid.readingTimeout 必须是大于0的数字')
        }
        if (typeof config.hardware.rfid.countdownInterval !== 'number'
          || config.hardware.rfid.countdownInterval < 100) {
          errors.push('hardware.rfid.countdownInterval 必须是大于等于100的数字(毫秒)')
        }
      }

      // 验证屏幕配置
      if (config.hardware.screen) {
        if (!config.hardware.screen.serialPort?.path) {
          errors.push('hardware.screen.serialPort.path 必须是有效的串口路径')
        }
        if (typeof config.hardware.screen.serialPort?.baudRate !== 'number'
          || config.hardware.screen.serialPort.baudRate <= 0) {
          errors.push('hardware.screen.serialPort.baudRate 必须是大于0的数字')
        }
        if (!config.hardware.screen.controlIds) {
          errors.push('hardware.screen.controlIds 配置缺失')
        }
        else {
          const requiredIds: (keyof ScreenControlIds)[] = ['cabinetIndex', 'fileCount', 'userName', 'status']
          requiredIds.forEach((id) => {
            if (!config.hardware?.screen.controlIds[id]) {
              errors.push(`hardware.screen.controlIds.${id} 必须是非空字符串`)
            }
          })
        }
      }
    }

    // 验证系统配置
    if (config.system?.messageQueue) {
      if (typeof config.system.messageQueue.maxLength !== 'number'
        || config.system.messageQueue.maxLength <= 0) {
        errors.push('system.messageQueue.maxLength 必须是大于0的数字')
      }
      if (typeof config.system.messageQueue.cleanupThreshold !== 'number'
        || config.system.messageQueue.cleanupThreshold <= 0) {
        errors.push('system.messageQueue.cleanupThreshold 必须是大于0的数字')
      }
    }
  }
  catch (error) {
    errors.push(`配置验证过程中发生错误: ${(error as Error).message}`)
  }

  return {
    isValid: errors.length === 0,
    errors,
  }
}

/**
 * 获取配置文件读取错误的解决建议
 */
function getConfigErrorSolution(error: Error, configPath: string): string {
  const errorMessage = error.message.toLowerCase()

  if (errorMessage.includes('enoent') || errorMessage.includes('no such file')) {
    return `配置文件不存在: ${configPath}，请创建配置文件或检查路径是否正确`
  }

  if (errorMessage.includes('eacces') || errorMessage.includes('permission')) {
    return `没有权限读取配置文件: ${configPath}，请检查文件权限`
  }

  if (errorMessage.includes('syntax') || errorMessage.includes('unexpected')) {
    return `配置文件JSON格式错误，请检查JSON语法是否正确`
  }

  if (errorMessage.includes('eisdir')) {
    return `指定的路径是目录而不是文件: ${configPath}`
  }

  return '请检查配置文件是否存在且格式正确'
}

/**
 * 加载配置文件
 */
export function loadConfig(): AppConfig {
  if (cachedConfig) {
    return cachedConfig
  }

  const resolvedPath = path.join(getProjectRoot(), 'config.json')

  try {
    // 检查文件是否存在
    if (!fs.existsSync(resolvedPath)) {
      logger.warn('配置模块: 配置文件不存在，使用默认配置', {
        path: resolvedPath,
        solution: '如需自定义配置，请创建config.json文件',
      })
      cachedConfig = defaultConfig
      return cachedConfig
    }

    // 检查文件状态
    const stats = fs.statSync(resolvedPath)
    if (!stats.isFile()) {
      throw new Error(`指定的路径不是文件: ${resolvedPath}`)
    }

    if (stats.size === 0) {
      throw new Error(`配置文件为空: ${resolvedPath}`)
    }

    if (stats.size > 1024 * 1024) { // 1MB
      logger.warn('配置模块: 配置文件过大', {
        path: resolvedPath,
        size: stats.size,
        solution: '配置文件不应超过1MB，请检查文件内容',
      })
    }

    // 读取文件内容
    const configContent = fs.readFileSync(resolvedPath, 'utf-8')

    if (!configContent.trim()) {
      throw new Error('配置文件内容为空')
    }

    // 解析JSON
    let userConfig: Partial<AppConfig>
    try {
      userConfig = JSON.parse(configContent) as Partial<AppConfig>
    }
    catch (parseError) {
      const err = parseError as Error
      throw new Error(`JSON解析失败: ${err.message}`)
    }

    // 验证配置
    const validation = validateConfig(userConfig)
    if (!validation.isValid) {
      logger.error('配置模块: 配置验证失败', {
        error: `配置验证失败: ${validation.errors.join('; ')}`,
        errors: validation.errors,
        solution: '请修正配置文件中的错误项',
      })

      // 如果有严重错误，抛出异常
      const criticalErrors = validation.errors.filter(error =>
        error.includes('必须') || error.includes('缺失'),
      )

      if (criticalErrors.length > 0) {
        throw new Error(`配置验证失败: ${criticalErrors.join('; ')}`)
      }
      else {
        logger.warn('配置模块: 存在非关键配置问题，将使用默认值补充')
      }
    }

    // 合并用户配置和默认配置
    cachedConfig = deepMerge(defaultConfig, userConfig)

    // 最终验证合并后的配置
    const finalValidation = validateConfig(cachedConfig)
    if (!finalValidation.isValid) {
      logger.warn('配置模块: 合并后的配置仍有问题', {
        errors: finalValidation.errors,
      })
    }

    logger.info('配置模块: 配置文件加载成功', {
      path: resolvedPath,
    })

    return cachedConfig
  }
  catch (error) {
    const err = error as Error
    const solution = getConfigErrorSolution(err, resolvedPath)

    logger.error('配置模块: 配置文件加载失败', {
      path: resolvedPath,
      error: err.message,
      solution,
      stack: err.stack,
    })

    logger.warn('配置模块: 使用默认配置')
    cachedConfig = defaultConfig
    return cachedConfig
  }
}

/**
 * 获取配置（单例模式）
 */
export function getConfig(): AppConfig {
  return loadConfig()
}

/**
 * 获取柜子配置
 */
export function getCabinetConfig(): CabinetConfig {
  return getConfig().cabinet
}

/**
 * 获取硬件配置
 */
export function getHardwareConfig(): HardwareConfig {
  return getConfig().hardware
}

/**
 * 获取系统配置
 */
export function getSystemConfig(): SystemConfig {
  return getConfig().system
}

/**
 * 获取锁配置
 */
export function getLockConfig(): LockConfig {
  return getConfig().hardware.lock
}

/**
 * 获取RFID配置
 */
export function getRfidConfig(): RfidConfig {
  return getConfig().hardware.rfid
}

/**
 * 获取屏幕配置
 */
export function getScreenConfig(): ScreenConfig {
  return getConfig().hardware.screen
}

/**
 * 获取消息队列配置
 */
export function getMessageQueueConfig(): MessageQueueConfig {
  return getConfig().system.messageQueue
}
